home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
4_0
/
ORBMECHD
/
LAMBERT.C
< prev
next >
Wrap
Text File
|
1991-02-18
|
10KB
|
412 lines
/********************************************************************
Karl Dishaw 8 Feb 91
Program for solution of Lambert's Problem using the Improved
Gauss' Method. Given the two radii, the angle between them,
and the time for the transfer, the semimajor axis and parameter
of an orbit is found.
Basic algorithm from Battin, Mathematics and Methods of Astrodynamics
Method in section 7.5, pp325-339. Implemented in C by Karl Dishaw.
**********************************************************************/
#include "orbmech.h"
#include "SANE.h"
#include "math.h"
#include "convert.h"
#define LAMBERTREC_SIZE 60
/* globals */
extern DialogPtr LambertDia, HohmannDia, HillsDia, KeplerDia, whichDialog, gHelpDia;
extern EventRecord gEvent;
extern TEHandle TEH;
extern decform gdecform;
extern int dirty;
extern Boolean gifWNE;
struct ParamRec
{
extended value;
Str255 name;
};
extern struct ParamRec gParameter;
struct LambertRec
{
extended flight_time, rad_one, rad_two, theta;
extended a, e;
} ;
typedef struct LambertRec *LambertPtr;
/*****************************************/
Lambert()
{
Handle inputH, itemHandle;
Str255 r1Str, r2Str, ftStr, thStr, aStr, eStr;
int itemType;
Rect itemRect;
Boolean dont_panic = 1, miFlag = 0, auFlag = 0;
decimal result;
ControlHandle kmSecBut, miHrBut, radBut;
struct LambertRec *data2;
Ptr temp;
Str255 q, w, e, r, t, y, u, i, o, p;
/* set up structure to hold data */
temp = NewPtr( LAMBERTREC_SIZE );
data2 = ( LambertPtr) temp;
/* initialize strings for record file */
pStrCopy("\p\rTime Specific Transfer ", q);
pStrCopy("\p\r radius 1: ", w);
pStrCopy("\p\r radius 2: ", e);
pStrCopy("\p\r angle: ", r);
pStrCopy("\p\r time: ", t);
pStrCopy("\p\r primary: ", y);
pStrCopy("\p\r\rTransfer orbit components ", u);
pStrCopy("\p\r semi-major axis: ", i);
pStrCopy("\p\r eccentricity: ", o);
pStrCopy("\p\r\r", p);
/* read data from dialogue box */
GetDItem( LambertDia, TIME, &itemType, &inputH, &itemRect);
GetIText( inputH, &ftStr );
Pstr_to_extended( &ftStr, &data2->flight_time, &dont_panic );
GetDItem( LambertDia, RAD_1, &itemType, &inputH, &itemRect);
GetIText( inputH, &r1Str );
Pstr_to_extended( &r1Str, &data2->rad_one, &dont_panic );
GetDItem( LambertDia, RAD_2, &itemType, &inputH, &itemRect);
GetIText( inputH, &r2Str );
Pstr_to_extended( &r2Str, &data2->rad_two, &dont_panic );
GetDItem( LambertDia, THETA, &itemType, &inputH, &itemRect);
GetIText( inputH, &thStr );
Pstr_to_extended( &thStr, &data2->theta, &dont_panic );
/* check radio buttons for units */
GetDItem ( LambertDia, KM_SEC, &itemType, &kmSecBut, &itemRect);
GetDItem ( LambertDia, MI_HR, &itemType, &miHrBut, &itemRect);
GetDItem ( LambertDia, RADIANS, &itemType, &radBut, &itemRect);
if ( dont_panic ) /* if data read successfully */
{
/* convert units */
if ( ! GetCtlValue ( kmSecBut ) )
if ( GetCtlValue ( miHrBut ) ) {
data2->rad_one *= MI_CONV;
data2->rad_two *= MI_CONV;
data2->flight_time *= HR_CONV;
miFlag = 1;
}
else {
data2->rad_one *= AU_CONV;
data2->rad_two *= AU_CONV;
data2->flight_time *= YR_CONV;
auFlag = 1;
}
if ( ! GetCtlValue ( radBut ) )
data2->theta /= DEG_CONV;
/* write problem starting conditions to file */
TEInsert( q+1, *q, TEH );
TEInsert( w+1, *w, TEH );
TEInsert( r1Str+1, *r1Str, TEH );
TEInsert( e+1, *e, TEH );
TEInsert( r2Str+1, *r2Str, TEH );
TEInsert( r+1, *r, TEH );
TEInsert( thStr+1, *thStr, TEH );
TEInsert( t+1, *t, TEH );
TEInsert( ftStr+1, *ftStr, TEH );
TEInsert( y+1, *y, TEH );
TEInsert( gParameter.name+1, *gParameter.name, TEH );
/* perform calculations */
lambert_calculations( data2 );
/* convert units */
if ( miFlag )
data2->a /= MI_CONV;
if ( auFlag )
data2->a /= AU_CONV;
/* convert data format */
if ( data2->a > 9999.0 || data2->a < .000001 )
gdecform.style = FLOATDECIMAL;
else
gdecform.style = FIXEDDECIMAL;
num2dec( &gdecform, data2->a, &result );
dec2str( &gdecform, &result, aStr );
if ( data2->e > 9999.0 || data2->e < .000001 )
gdecform.style = FLOATDECIMAL;
else
gdecform.style = FIXEDDECIMAL;
num2dec( &gdecform, data2->e, &result );
dec2str( &gdecform, &result, eStr );
/* write results to file */
TEInsert( u+1, *u, TEH );
TEInsert( i+1, *i, TEH );
TEInsert( aStr+1, *aStr, TEH );
TEInsert( o+1, *o, TEH );
TEInsert( eStr+1, *eStr, TEH );
TEInsert( p+1, *p, TEH );
dirty = 1;
/* write results to dialogue box */
GetDItem( LambertDia, A, &itemType, &itemHandle, &itemRect);
SetIText( itemHandle, aStr );
GetDItem( LambertDia, E, &itemType, &itemHandle, &itemRect);
SetIText( itemHandle, eStr );
ShowSelect();
}
}
/**************************************/
lambert_calculations( data2 )
struct LambertRec *data2;
{
extended mu, deltat, r1, r2, theta, rop, m, l, x;
extended epsilon, omegaf, zeta, h1, h2, b, u, k;
extended y, t, a, e2, e, tva, tvb;
int converged, la, lb;
Str255 warn;
extended cfa(), cfb();
mu = gParameter.value; /* km^3 / sec^2 */
deltat = data2->flight_time; /* transfer time in seconds */
r1 = data2->rad_one; /* radii of starting and destination points in km */
r2 = data2->rad_two;
theta = data2->theta; /* angle between ra and rb in radians */
pStrCopy("\p\r\rSTOP! Calculation interrupted, results invalid", warn);
epsilon = r2 / r1 - 1.0;
/* 7.56 */
omegaf = epsilon * epsilon / 4.0 / ( sqrt( r2 / r1 )
+ r2 / r1 * ( 2 + sqrt( r2 / r1 ) ) );
/* 7.57 */
tva = cos( theta / 4.0 ) * cos( theta / 4.0 ) + omegaf;
tvb = sin( theta / 4.0 ) * sin( theta / 4.0 ) + omegaf;
/* temporary variables */
rop = sqrt( r1 * r2 ) * tva;
/* 7.102 */
m = mu * deltat * deltat / ( 8.0 * rop * rop * rop );
/* 7.89 (3) */
if ( theta < 3.14159 ) {
l = tvb / ( tvb + cos( theta / 2.0 ) );
}
else {
l = ( tva - cos( theta / 2.0 ) ) / tva;
}
/* 7.101 */
x = l;
converged = 0;
while ( !converged ) {
zeta = cfa( x );
/* 7.121 */
h1 = ( l + x ) * ( l + x ) * ( 1.0 + 3.0 * x + zeta )
/ ( ( 1 + 2.0 * x + l ) * ( 4.0 * x + zeta * ( 3.0 + x )));
/* 7.111 */
h2 = m * ( x - l + zeta ) / ( 1.0 + 2.0 * x + l )
/ ( 4.0 * x + zeta * ( 3.0 + x ) ) ;
/* 7.112 */
b = 27.0 * h2 / ( 4.0 * ( 1.0 + h1 ) * ( 1.0 + h1 ) * ( 1.0 + h1 ));
/* 7.123 (2) */
u = b / 2.0 / ( sqrt( 1.0 + b ) + 1.0 );
/* 7.123 (1) */
k = cfb( u );
/* 7.125 */
y = ( 1.0 + h1 ) / 3.0 * ( 2.0 + sqrt( 1.0 + b )
/ ( 1.0 + 2.0 * u * k * k ) );
/* 7.124 */
t = sqrt( ( ( 1.0 - l ) / 2.0 ) * ( ( 1.0 - l ) / 2.0 )
+ m / y / y ) - ( 1.0 + l ) / 2.0;
/* 7.113 */
converged = checkConvergence( x, t);
if ( !converged ) {
if ( gifWNE )
WaitNextEvent( everyEvent, &gEvent, MIN_SLEEP, NIL_MOUSE_REGION );
else
{
SystemTask();
GetNextEvent( everyEvent, &gEvent );
}
if ( (gEvent.modifiers & cmdKey) != 0 && ( ( gEvent.what == keyDown )
|| ( gEvent.what == autoKey ) ) && ( gEvent.message & charCodeMask )
== POINT )
{
StopAlert( INTERRUPT, NIL_POINTER );
TEInsert( warn+1, *warn, TEH );
converged = 1;
}
}
x = t;
}
a = mu * deltat * deltat / ( 16.0 * r1 * r2 * tva * tva * x * y * y );
/* 7.103 */
e2 = ( epsilon * epsilon + 4.0 * r2 / r1 * sin( theta / 2.0 )
* sin( theta / 2.0 ) * (( l - x ) / ( l + x ))
* (( l - x ) / ( l + x ))) / ( epsilon * epsilon +
4.0 * r2 / r1 * sin( theta / 2.0 ) * sin( theta / 2.0 ) );
/* 7.106 */
e = sqrt( e2 );
data2->a = a; /* pass results back */
data2->e = e;
}
/**************************************/
extended cfa(x) /* top-down calculation of continued fraction */
extended x;
{
/* reference Battin p311, pp335-7 */
extended delta, deltaprev, sum, zeta;
extended u, gamma, eta;
int i, converged;
eta = x / ( ( sqrt( 1.0 + x ) + 1.0 ) * (sqrt(1.0 + x ) + 1.0 ));
i = 1;
deltaprev = 1.0;
sum = 1.0;
u = 1.0;
converged = 0;
while(!converged){
gamma = - (i + 3.0) * (i + 3.0) / ( 2.0 * i + 5.0) / ( 2.0 * i + 7.0);
delta = 1.0 / ( 1.0 - gamma * eta * deltaprev);
u *= delta - 1.0;
sum += u;
converged = checkConvergence( u, 0.0 );
deltaprev = delta;
i++;
}
zeta = 8.0 * ( sqrt( 1.0 + x ) + 1.0 ) / ( 3.0 + 1.0 /
( 5.0 + eta + 9.0 * eta / 7.0 / sum ) );
return ( zeta);
}
/**************************************/
extended cfb(z) /* top-down calculation of continued fraction */
extended z;
{
/* reference Battin p311, p339 */
double m, n, gamma, u, delta, sum, deltaprev, k;
int odd, i, converged, j;
odd = 1;
i = 1;
u = 1.0;
sum = 1.0;
deltaprev = 1.0;
converged = 0;
while(!converged){
if(odd){
j = (i - 1) / 2;
m = -2.0 * ( 3.0 * j + 2.0) * ( 6.0 * j + 1.0 );
n = 9.0 * (4.0 * j + 1.0) * (4.0 * j + 3.0);
gamma = m / n;
}
else{
j = i / 2;
m = - 2.0 * (3.0 * j + 1.0) * ( 6.0 * j - 1.0);
n = 9.0 * (4.0 * j - 1.0) * ( 4.0 * j + 1.0);
gamma = m / n;
}
delta = 1.0 / ( 1.0 - gamma * z * deltaprev);
u *= delta - 1.0;
sum += u;
converged = checkConvergence( u, 0.0 );
deltaprev = delta;
i++;
odd = !odd;
}
k = sum / 3.0;
return (k);
}
/**********************************************/
checkConvergence( a, b)
extended a, b;
{
/* check whether two numbers are effectively equal */
Boolean success = 0, flag1, flag2;
extended limit = 1.0e-6, diff, var, zero = 0.0;
diff = a - b;
var = diff / a;
if ( b == 0.0 )
var = a;
flag1 = ( var >= zero ) && ( var < limit);
flag2 = ( var < zero ) && ( var > -limit);
success = flag1 || flag2;
return ( success );
}